/**
 * @Author: yzy
 * @Description:
 * @Version: 1.0.0
 * @Date: 2021/5/17 上午1:13
 * @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
 */
package main

import (
	"fmt"
	"github.com/jessevdk/go-flags"
	"go.uber.org/dig"
	"log"
	"os"
	"time"
	"vpn-management-server/config"
	"vpn-management-server/logger"
	"vpn-management-server/network"
	"vpn-management-server/security/keymanager"
	"vpn-management-server/src/controller/usercontroller"
	"vpn-management-server/src/dao"
	"vpn-management-server/src/router"
	"vpn-management-server/src/service/authservice"
	"vpn-management-server/src/service/userlogservice"
	"vpn-management-server/src/service/userservice"
)

type option struct {
	ConfigPath string `short:"c" long:"config" description:"the location of config file" default:"vpn.ini"`
	Show       bool   `short:"s" long:"show" description:"show the config file"`
	Version    string `short:"v" long:"version" description:"the version of vms" default:"v1.0.0"`
}

func newOption() *option {
	var opt option
	var err error
	parser := flags.NewNamedParser("COMMAND OF VMS", flags.Default)
	_, err = parser.AddGroup("Application Options", "", &opt)
	_, err = parser.Parse()
	if err != nil {
		os.Exit(-1)
	}
	return &opt
}
func newConfig(opt *option) *config.VPNConfig {
	config.Cfg = config.ParseConfig(opt.ConfigPath, opt.Show)
	return config.Cfg
}

func BuildContainer() *dig.Container {
	container := dig.New()
	_ = container.Provide(newOption)
	_ = container.Provide(newConfig)
	return container
}

func vmsShow() {
	var vms = "\033[1;35;48m _     _       ___  ___   _____  \n| |   / /     /   |/   | /  ___/ \n| |  / /     / /|   /| | | |___  \n| | / /     / / |__/ | | \\___  \\ \n| |/ /     / /       | |  ___| | \n|___/     /_/        |_| /_____/  \033[0m "
	fmt.Fprintln(os.Stdout, vms)
}

func main() {
	// 依赖注入
	container := BuildContainer()
	err := container.Invoke(func(VpnConfig *config.VPNConfig) {
		vmsShow()
		config.Cfg = VpnConfig
		logger.Logger.Init(VpnConfig)
		dao.GMysqlDB.Init(VpnConfig)
		dao.RdsClient.Init(VpnConfig.RedisConfig)
		network.Init(VpnConfig)
		authservice.Init(VpnConfig.SessionConfig)
		userservice.Init(VpnConfig.MinSDKConfig)
		userlogservice.Init(VpnConfig)
		key := keymanager.New(VpnConfig.FESSLConfig.Pubkey, VpnConfig.FESSLConfig.Prikey)
		RecoverCoroutines("StartMINRouter", router.StartMINRouter, 5*time.Second)
		RecoverCoroutines("StartCPacketRouter", router.StartCPacketRouter, 5*time.Second)
		RecoverCoroutines("StartMINSecRouter", router.StartMINSecRouter, 5*time.Second)
		// go router.StartMINRouter()
		// go router.StartCPacketRouter()
		go router.StartSecRouter(VpnConfig.GetFEAddress(), VpnConfig.GetFESSLAddress(), key)
		// go router.StartMINSecRouter()
		// 开启SIM卡认证回调监听
		go usercontroller.StartHandleSimAuthCallback()
		select {}
	})

	if err != nil {
		panic(err)
	}

}

func RecoverCoroutines(name string, f func() error, duration time.Duration) {
	go func() {

		for {
			if err := f(); err != nil {
				log.Printf("----------[%s] restart ----------\n", name)
				time.Sleep(duration)
			}
		}

	}()
}
